﻿using EFCoreDemo.Entity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Linq.Expressions;

namespace EFCoreDemo.Database
{
    public class DatabaseContext : DbContext
    {
        private readonly ILoggerFactory loggerFactory;
        public DatabaseContext() : base()
        {
        
        }
        public DatabaseContext(ILoggerFactory loggerFactory) : base()
        {
            this.loggerFactory = loggerFactory;
        }
        public DatabaseContext(ILoggerFactory loggerFactory, Action<DbContextOptionsBuilder> extraConfiguring) : base()
        {
            this.loggerFactory = loggerFactory;
            this.extraConfiguring  = extraConfiguring;
        }
        private Action<DbContextOptionsBuilder> extraConfiguring;
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);
            optionsBuilder.UseSqlServer(@"Server=.;database=EFCoreDemo;uid=sa;pwd=123456;");
            optionsBuilder.UseLoggerFactory(loggerFactory);
            //optionsBuilder.UseLoggerFactory(LoggerFactory.Create(build => build.AddConsole()));
            extraConfiguring?.Invoke(optionsBuilder);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            var entityType = typeof(IEntity);
            var types = entityType.Assembly.GetTypes().Where(x => entityType.IsAssignableFrom(x) && x.IsClass && !x.IsAbstract);
            foreach (var item in types)
            {
                modelBuilder.Model.AddEntityType(item);
                var entity = modelBuilder.Entity(item);

                if (typeof(IHasSoftDelete).IsAssignableFrom(item))
                {
                    entity.Property<bool>("IsDeleted").HasDefaultValue(0);
                    var exprParam = Expression.Parameter(item, "v");
                    entity.HasQueryFilter(Expression.Lambda(Expression.Equal(Expression.Call(typeof(EF).GetMethod("Property").MakeGenericMethod(typeof(bool)), new Expression[] { exprParam, Expression.Constant("IsDeleted") }), Expression.Constant(false)), new[] { exprParam }));
                }
            }

            var ent = modelBuilder.Entity<User>();
            ent.Property(p => p.Sex).HasConversion<string>().HasMaxLength(50);
        }
    }
}
